<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
</head>
    <p>点击1</p>
    <p>点击2</p>
    <p>点击3</p>
    <p>点击4</p>
<body>
    <script>
        // (function () {
        //     console.log(1);

        //     // setTimeout是一个异步任务 要挂起 再往后执行 同步任务执行完毕 再回来执行异步任务
        //     setTimeout(function () {
        //         console.log(2);
        //     }, 0)

        //     console.log(3);
        //     console.log(4)

        //     setTimeout(function () {
        //         console.log(5);
        //     }, 100)

        //     // 1,3,4,2,5
        // })();

        // (function () {
        //     console.log("A")
        //     // while 是一个同步任务 从上往下一次执行 但while是一个死循环 永远也执行不完
        //     while(true){

        //     }
        //     console.log("B");

        //     // 只输出 A 无法执行到B
        // })();

        // (function () {
        //     console.log("A");
        //     // 异步任务
        //     setTimeout(() => {
        //         console.log("B")
        //     }, 0);
        //     // 同步任务
        //     while(1){

        //     }

        //     // 只输出A  异步任务挂起 往后执行同步任务完毕后再回来执行异步任务 但while（1） 是一个死循环 
        // })();

        (function () {
            // ES6
            for (let index = 0; index < 4; index++) {
                console.log("我第一执行")
                setTimeout(() => {
                    console.log(index); //0,1,2,3
                }, 500);
            }
            console.log(index); //undefined  es6 有块级作用域 在{} 外访问不了变量

            // ES5
            // 异步任务的放入时间和执行时间 js中有一个time模块定时器 专门处理settimeout等 
            // 当for循环体内执行到settimeout 将settimeout交给time模块，
            // 而没有放入异步队列中 然后直接执行后续内容 i++，
            // 当执行完了for循环之后 此时异步队列也没有任何东西
            // 而是再到了一定时间才把settimeout放入异步队列中
            // 依靠 事件循环 的机制 依次执行settimeout语句 此时的i是4 所以输出4
            for (var index = 0; index < 4; index++) {
                console.log("我第二执行")
                setTimeout(function () {
                    console.log(index); //4,4,4,4
                }, 500);
            }

            // 为什么这个语句最先执行，其实并不是，他是在执行完了for循环之后才执行的
            // 因为并不是for循环执行完了就执行setTimeout 其实要等到一定的时间才把settimeout放入异步队列中
            // 依靠 事件循环 的机制 依次执行settimeout语句 
            // 而在这个时间内就执行了往后的语句 所以先输出了以下语句
            console.log(index); //4  es5 没有块级作用域 在{} 可以访问变量index

            for (var i = 0; i < 4; i++) {
                // 立即执行 在函数内部又返回了一个匿名函数，匿名函数保存了外层函数num的副本即活动对象所以能输出0,1,2,3
                // 利用闭包只能取得包含函数中任何变量的最后一个值
                document.getElementsByTagName("p")[i].onclick = function (num) {
                   return function(){
                       console.log(num);//0,1,2,3
                   }
                }(i);
            }

            console.log("我是最终的i值：" + i);
        })();
    </script>
</body>

</html>